Skip to content

switch to GA4 event structure #5914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 3, 2024
Merged

Conversation

escattone
Copy link
Contributor

@escattone escattone commented Mar 6, 2024

mozilla/sumo#1646

This PR switches our GA events from their current GA3 event structure (category, action, label) to the new GA4 structure of an event name with zero or more event parameters.

It assumes that its complementary PR -- that sets the proper GA4 value for GTM_CONTAINER_ID -- will be merged prior to deploying this PR.

Notes

  • I will remove all of the console.log calls and the debug_mode configuration before merging.

  • This PR does not address the changes needed to convert kitsune/sumo/googleanalytics.py to use the Analytics Data API for GA4. That work is tracked with [GA4] Convert current GA API queries to use the Analytics Data API for GA4 sumo#1705.

  • It's best to start reviewing by looking at analytics.js and gtm-snippet.js, as together they implement the core functionality.

  • In GA4, there are many events which are sent automatically. Some of the most important ones are:

    • page_view -- Sent when the page loads.
    • click -- Sent when user clicks on links to external domains. It is not sent for clicks on links to internal targets.
    • form_submit -- Sent when a form is submitted.
  • All custom event names have been standardized on the <noun>_<verb> format, with the noun in snake-case if it has more than one word.

  • There are a set of parameters that are configured to be sent with all GA4 events sent from a page, and they are:

    • content_group -- This one is a key new event parameter that allows us to bucket all page views into groups, for example kb-article or kb-cms or product-home, and so on. Eventually, all of our pages will include a content-group, but currently some pages, like our dashboard pages for example, do not yet have this defined. See [GA4] Implement the GA4 content_group parameter for all pages sumo#1708.
    • default_slug -- This one is currently only defined for KB article pages. It provides the article's parent.slug if the article is a translation, and the slug otherwise.
    • locale -- The locale of the page (e.g., en-US or de). This is always defined and sent.
    • products -- All of the products related to the page, if any, where each product is represented by its slug wrapped in forward slashes, so for example /firefox/ or /mobile/ or, in the case when multiple products are involved, /firefox/mobile/ios/. This will always be present, for example, for a product home page or a product-and-topic home page, or any other page that's associated with a product. This parameter allows us to group page views and other events into product buckets.
    • topics -- All of the topics related to the page, if any, where each topic is represented by its slug wrapped in forward slashes, so for example /fix-problems/ or /sync-and-save/ or, in the case when multiple topics are involved, /fix-problems/sync-and-save/. This will always be present, for example, for a product-and-topic home page, or any other page that's clearly associated with a topic. This parameter allows us to group page views and other events into topic buckets.
  • analytics.js has been converted to vanilla JS and greatly simplified.

    • Now all HTML elements that have the data-event-name attribute defined will have a event listener added that will make a trackEvent() call when the element is clicked.

    • Another big change is that we no longer delay the original click event for 250ms in order to make time for the trackEvent() call in case we're leaving the current page. That may have been needed in the past, but no longer. See this GA4 doc, specifically under the section Event batching for Google Analytics 4 properties, where you'll see the following comment:

      If any events are still held client-side when the user leaves the page (e.g. by navigating to another page), those events are sent immediately

    • It exports a new function called addGAEventListeners that can be used to instrument dynamically-added DOM content, as is done for "instant" search results (see kitsune/sumo/static/sumo/js/instant_search.js).

    • For link_click events, it automatically adds the link_url event parameter if it hasn't been already added.

  • There are huge changes to the GA search events, all for the better.

    • The old GA3 search events were effectively useless, at least from the point of view of getting any use out of them via the GA3 dashboard(s). Not only because the built-in GA3 search dashboard only reflected the search page events, and not the instant search events -- which are the vast majority of search events -- but also because the primary data point of interest, the search term, was deeply embedded in the search URL, and so could not be isolated for finding the most common search terms.
    • The new GA4 search events use the recommended search event name and search_term event parameter, with the following added custom event parameters:
      • search_product_filter
      • search_content_filter
    • Another key change is that all search events flow into this same new structure -- both the instant search events and the search page events -- which provides the ability to create a unified view of search in GA4 that we never had in GA3.
  • All existing GA3 events have been converted to the new GA4 structure, except for three of them, which no longer made sense or were never triggered anyway:

    • data-event-category=Instant Search, data-event-action=Exit Search, and data-event-label=(search query URL)
    • data-event-category=Ask A Question flow, data-event-action=step 3 confirmed page
    • data-event-category=navigation, data-event-action=main navigation, and data-event-label=Contributor Tools
  • New GA4 events have been added.

  • While QA'ing the GA4 events in this PR, @emilghittasv discovered that the device-migration wizard never reported some GA events.

  • document_macros.html has been cleaned up.

    • The kb_subtopic_documents and kb_subtopic_tabs macros were removed, since they were not used.
  • search.js has been cleaned-up and converted to vanilla JS.

    • All of the jQuery and jQuery-UI-based code wasn't used, so I removed it.
    • All that remains is the new code to track search events for the search landing page, and that code uses vanilla JS.
    • As part of that effort, I changed the code in ajaxvote.js that triggers a jQuery vote event, to instead dispatch a vanilla DOM vote event. All of our code that listens for that vote event has been converted to vanilla JS, so there's no longer a need to trigger the jQuery vote event. Note that this was necessary because vanilla JS event listeners are not triggered by jQuery events.
  • wiki.metrics.js has been converted to vanilla JS. It no longer depends on jQuery.

  • questions.metrics.js has been converted to vanilla JS. It no longer depends on jQuery.

  • The topic argument of the product_cards() macro within kitsune/products/jinja2/products/includes/product_macros.html was removed. It was never used, so always set to its default value of None.

Next Steps

@escattone escattone changed the title Switch to GA4 switch to GA4 events Mar 6, 2024
@escattone escattone force-pushed the switch-to-GA4 branch 9 times, most recently from 06f7022 to 60a9191 Compare March 12, 2024 23:34
@escattone escattone changed the title switch to GA4 events switch to GA4 event structure Mar 12, 2024
@escattone escattone force-pushed the switch-to-GA4 branch 10 times, most recently from 69b0095 to 629bf4f Compare March 19, 2024 23:42
@escattone escattone force-pushed the switch-to-GA4 branch 3 times, most recently from 6f81cfb to 4630dcc Compare March 26, 2024 17:39
@escattone escattone marked this pull request as ready for review March 26, 2024 23:31
@escattone escattone requested a review from smithellis March 26, 2024 23:32
@escattone escattone requested a review from akatsoulas March 27, 2024 19:27
Copy link
Contributor

@smithellis smithellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two questions but nothing to stop an approval from me.

Copy link
Collaborator

@akatsoulas akatsoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work! I added a few comments some of which need to be addressed before merging but I am not blocking the review.

Regarding merging itself, this PR needs a bit of restructuring around the commits. I would advice to bundle commits contextually. Eg remove unused code one commit, functionality needed to get GA4 to work another one etc etc. Maybe a couple could be dropped (eg adding/removing debugging symbols)?
We need to be able to revert a single commit to restore a previous state.

Great work 🚀

@@ -5,3 +5,6 @@
{% if product %}
{% set search_params = {'product': product.slug} %}
{% endif %}
{% if not ga_content_group %}
{% set ga_content_group = "kb-other" %}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to set this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of this as a default value for ga_content_group for any future wiki page that didn't set it, so at least the new page is placed within a KB bucket rather than being placed within the (unset) content group. However, I'm fine with removing it too.

@@ -2,3 +2,6 @@
{% if not scripts %}
{% set scripts = ('questions',) %}
{% endif %}
{% if not ga_content_group %}
{% set ga_content_group = "support-forums-other" %}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the other comment on a base template. Is this needed? Or rephrasing, this will be always set with every page that extends it

Copy link
Contributor Author

@escattone escattone Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not necessary, but I was thinking of this as a default value.

@escattone escattone force-pushed the switch-to-GA4 branch 9 times, most recently from bee994a to d8930a0 Compare April 3, 2024 00:22
Copy link
Collaborator

@akatsoulas akatsoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+wc :shipit:

Copy link
Collaborator

@akatsoulas akatsoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+wc :shipit:

@escattone escattone merged commit 2e0eff0 into mozilla:main Apr 3, 2024
@escattone escattone deleted the switch-to-GA4 branch April 3, 2024 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants